﻿using Cube.Data;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace CubeForm
{
    class CubePainter
    {
        private Cube.Data.Cube cube;
        private Graphics graphics;
        private int size = 55;
        private int leak = 3;
        public CubePainter(Cube.Data.Cube cube, Graphics g)
        {
            this.cube = cube;
            graphics = g;
        }

        /// <summary>
        /// X斜二测坐标转换为直角坐标
        /// </summary>
        public PointF ScaleTransformX(PointF point, PointF offset)
        {
            var a = 0.35355339059327; //四分之根号2
            var x = point.X * a + offset.X;
            var y = point.Y - point.X * a + offset.Y; 
            return new PointF((float)x, (float)y);
        }

        /// <summary>
        /// Y斜二测坐标转换为直角坐标
        /// </summary>
        public PointF ScaleTransformY(PointF point, PointF offset)
        {
            var a = 0.35355339059327; //四分之根号2
            var x = point.X - point.Y * a + offset.X + a * 3 * size + leak;
            var y = point.Y * a + offset.Y + (1 - a) * 3 * size + leak;
            return new PointF((float)x, (float)y);
        }

        public void Draw()
        {
            var startPoint = new Point(0, 0);
            var up = cube.GetFace(Faces.Up);
            var right = cube.GetFace(Faces.Right);
            var front = cube.GetFace(Faces.Front);
            DrawFace(up, new Point(startPoint.X + 4 * (size + leak), startPoint.Y + (size + leak)), ScaleType.Y);
            DrawFace(front, new Point(startPoint.X + 4 * (size + leak), startPoint.Y + 4 * (size + leak)), ScaleType.Normal);
            DrawFace(right, new Point(startPoint.X + 7 * (size + leak), startPoint.Y + 4 * (size + leak)), ScaleType.X);
        }

        private void DrawFace(CubeColor[,] face, Point s, ScaleType scale)
        {
            var startX = s.X;
            var startY = s.Y;
            var startP = (PointF)s;
            for (var i = 0; i < 3; i++)
            {
                for (var j = 0; j < 3; j++)
                {
                    switch (scale)
                    {
                        case ScaleType.Normal:
                            graphics.FillRectangle(GetBrush(face[i, j]), startX + j * (size + leak), startY + i * (size + leak), size, size);
                            break;
                        case ScaleType.X:
                            graphics.FillPolygon(GetBrush(face[i, j]), new PointF[]
                            {
                                ScaleTransformX(new PointF(j * (size + leak), i * (size + leak)), startP),
                                ScaleTransformX(new PointF(j * (size + leak) + size, i * (size + leak)), startP),
                                ScaleTransformX(new PointF(j * (size + leak) + size, i * (size + leak)  +size), startP),
                                ScaleTransformX(new PointF(j * (size + leak), i * (size + leak) + size), startP)
                            });
                            break;
                        case ScaleType.Y:
                            graphics.FillPolygon(GetBrush(face[i, j]), new PointF[]
                            {
                                ScaleTransformY(new PointF(j * (size + leak), i * (size + leak)), startP),
                                ScaleTransformY(new PointF(j * (size + leak) + size, i * (size + leak)), startP),
                                ScaleTransformY(new PointF(j * (size + leak) + size, i * (size + leak)  +size), startP),
                                ScaleTransformY(new PointF(j * (size + leak), i * (size + leak) + size), startP)
                            });
                            break;
                    }
                }
            }
        }

        private enum ScaleType
        {
            Normal,
            X,
            Y
        }

        private Brush GetBrush(CubeColor color)
        {
            switch (color)
            {
                case CubeColor.Blue:
                    return Brushes.Blue;
                case CubeColor.Green:
                    return Brushes.Green;
                case CubeColor.Orange:
                    return Brushes.Orange;
                case CubeColor.Red:
                    return Brushes.Red;
                case CubeColor.White:
                    return Brushes.Black;
                case CubeColor.Yellow:
                    return Brushes.Yellow;
                default:
                    throw new Exception();
            }
        }
    }
}
